import { NBT, Tags } from "prismarine-nbt";
import { _TargetSelector } from "./selector";
import { Float, Integer } from "./basic";

export type Angle = {
    type: "angle";
    value: Float;
    relative: boolean;
};

export type _RelativePosPart<T extends Integer | Float = Integer> = {
    type: "_relative_pos_part";
    value: T;
};

export type _LocalPosPart<T extends Integer | Float = Integer> = {
    type: "_local_pos_part";
    value: T;
};

export type _AbsolutePosPart<T extends Integer | Float = Integer> = {
    type: "_absolute_pos_part";
    value: T;
};

export type _PosPart<T extends Integer | Float = Integer> =
    | _RelativePosPart<T>
    | _LocalPosPart<T>
    | _AbsolutePosPart<T>;
export type _BlockPosPart = _PosPart<Integer>;

export type Vec2 = {
    type: "vec2";
    value: {
        [coordinate in "first" | "second"]: _BlockPosPart;
    };
};

export type Vec3 = {
    type: "vec3";
    value: {
        [coordinate in "x" | "y" | "z"]: _BlockPosPart;
    };
};

export type _BlockTag = {
    type: "_block_tag";
    value: string;
};

export type _BlockType = {
    type: "_block_type";
    value: string;
};

export type BlockPredicate = {
    type: "block_predicate";
    value: {
        block: _BlockTag | _BlockType;
        blockstates?: Record<string, string>;
        nbt?: NBT;
    };
};

export type BlockState = {
    type: "block_state";
    value: {
        block: _BlockType;
        blockstates?: Record<string, string>;
        nbt?: NBT;
    };
};

export enum ColorCollection {
    Black = "black",
    DarkBlue = "dark_blue",
    DarkGreen = "dark_green",
    DarkAqua = "dark_aqua",
    DarkRed = "dark_red",
    DarkPurple = "dark_purple",
    Gold = "gold",
    Gray = "gray",
    DarkGray = "dark_gray",
    Blue = "blue",
    Green = "green",
    Aqua = "aqua",
    Red = "red",
    LightPurple = "light",
    Yellow = "yellow",
    White = "white",
}

export type Color = {
    type: "color";
    value: "reset" | ColorCollection;
};

export type ColumnPos = {
    type: "column_pos";
    value: {
        [coordinate in "x" | "z"]:
            | _AbsolutePosPart<Integer>
            | _RelativePosPart<Integer>;
    };
};

export type Component = {
    type: "component";
    value: any;
};

export type Dimension = {
    type: "dimension";
    value: string;
};

export type _PlayerName = {
    type: "_player_name";
    value: string;
};

export type UUID = {
    type: "uuid";
    value: string;
};

export type Entity = {
    type: "entity";
    value: _PlayerName | UUID | _TargetSelector;
};

export type EntityAnchor = {
    type: "entity_anchor";
    value: "eyes" | "feet";
};

export type _Range<T extends Integer | Float> = {
    min?: T;
    max?: T;
};

export type FloatRange = {
    type: "float_range";
    value: _Range<Float>;
};

export type IntRange = {
    type: "int_range";
    value: _Range<Integer>;
};

export type Function = {
    type: "function";
    value: string;
};

export type GameMode = {
    type: "game_mode";
    value: "survival" | "creative" | "adventure" | "spectator";
};

export type HeightMap = {
    type: "height_map";
    value:
        | "world_surface"
        | "motion_blocking"
        | "motion_blocking_no_leaves"
        | "ocean_floor";
};

export type _ItemComponentTestEntry = {
    type: "_item_component_test_entry";
    value: {
        id: string;
        value?: NBT;
        sub?: NBT;
    };
};

export type _ItemCountTestEntry = {
    type: "_item_count_test_entry";
    value: {
        count: Integer | IntRange;
    };
};

export type _ItemTestEntry = {
    exclude: boolean;
    entries: (_ItemComponentTestEntry | _ItemCountTestEntry)[];
};

export type ItemPredicate = {
    type: "item_predicate";
    value: {
        type: string;
        testEntries: _ItemTestEntry[];
    };
};

export type ItemSlot = {
    type: "item_slot";
    value: {
        type: string;
        number?: number;
    };
};

export type ItemSlots = {
    type: "item_slots";
    value: {
        type: string;
        number?: number | "*";
    };
};

export type ItemStack = {
    type: "item_stack";
    value: Record<string, NBT>;
};

export type Message = {
    type: "message";
    value: string;
};

export type NBTCompoundTag = {
    type: "nbt_compound_tag";
    value: NBT;
};

export type NBTPath = {
    type: "nbt_path";
    value: string;
};

export type NBTTag = {
    type: "nbt_tag";
    value: Tags[keyof Tags];
};

export type Objective = {
    type: "objective";
    value: string;
};

export type ObjectiveCriteria = {
    type: "objective_criteria";
    value: string;
};

export type Operation = {
    type: "operation";
    value: "string";
};

export type Particle = {
    type: "particle";
    value: {
        id: string;
        arguments: string[];
    };
};

export type ScoreboardSlot = {
    type: "scoreboard_slot";
    value: string;
};

export type Swizzle = {
    type: "swizzle";
    value: {
        x: boolean;
        y: boolean;
        z: boolean;
    };
};

export type TemplateMirror = {
    type: "template_mirror";
    value: "none" | "front_back" | "left_right";
};

export type TemplateRotation = {
    type: "template_rotation";
    value: "none" | "clockwise_90" | "counterclockwise_90" | "180";
};

export type Time = {
    type: "time";
    value: {
        type: "day" | "second" | "tick";
        value: number;
    };
};

export type Team = {
    type: "team";
    value: string;
};
